﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using VsSourceCpoy.Entity;
using VsSourceCpoy.Helper;
using System.IO;

namespace VsSourceCpoy.Service
{
    public class CSharpSolutionCopy : ISolutionCopy
    {
        private SolutionFileParserBase fileParser;

        public SolutionFileParserBase FileParser
        {
            get
            {
                fileParser = fileParser ?? new CSharpSolutionFileParser();
                return fileParser;
            }
            set
            {
                fileParser = value;
            }
        }

        public FileCopyHelper fch = new FileCopyHelper();

        #region ISolutionCopy 成员
        public SolutionCopyResult Copy(SolutionCopyContext context)
        {
            SolutionCopyResult scr = new SolutionCopyResult();
            if (VsVersionCheck.GetVsVersionFromSlnFile(context.FromFileName) == VSVersion.VS2010)
            {
                FileParser.SlnFileParser = new Vs2010CSharpSolutionFileParser();
                scr.VSVersion = "VS2010";
            }
            else if (VsVersionCheck.GetVsVersionFromSlnFile(context.FromFileName) == VSVersion.VS2008)
            {
                FileParser.SlnFileParser = new Vs2008CSharpSolutionFileParser();
                scr.VSVersion = "VS2008";
            }
            else
            {
                throw new VersionUnsupportException("版本错误，现支持VS2010和VS2008");
            }

            ParseResult sfpr = fileParser.ParseFile(context.FromFileName, Encoding.UTF8);
            HashSet<string> res = sfpr.AllFileList;
            fch.CopyListener = context.CopyListener;
            if (context.OverWrite && Directory.Exists(context.ToPath))
            {
                Directory.Delete(context.ToPath, true);
            }
            List<string> copyedFileList = new List<string>();
            List<string> ignoreFileList = new List<string>();

            foreach (string file in res)
            {
                string toFileName = file.Replace(sfpr.CopyFromRoot.FullName, context.ToPath);
                if (!IsSubDir(sfpr.CopyFromRoot.FullName, Path.GetDirectoryName(file)))
                {
                    ignoreFileList.Add(new DirectoryInfo(file).FullName);
                    continue;
                }
                bool success = fch.Copy(file, toFileName, true);
                if (success)
                {
                    copyedFileList.Add(toFileName);
                }
            }

            scr.CopyedCsprojList = new List<string>(sfpr.CsprojFileList);
            scr.CopyedSlnList = new List<string>(sfpr.SlnFileList);
            scr.CopyedFileList = copyedFileList;
            scr.IgnoreList = ignoreFileList;
            return scr;
        }
        #endregion

        private bool IsSubDir(string parent, string testPath)
        {
            DirectoryInfo diP = new DirectoryInfo(parent);
            DirectoryInfo diT = new DirectoryInfo(testPath);
            if (!diP.Exists || !diT.Exists)
            {
                return false;
            }
            DirectoryInfo parentDir = diT;

            do
            {
                if (parentDir.FullName.Equals(diP.FullName, StringComparison.OrdinalIgnoreCase))
                {
                    return true;
                }
                diT = parentDir;
            } while ((parentDir = diT.Parent) != null);
            return false;
        }
    }
}
